use std::fs::File;
use std::io::{BufRead, BufReader, Error, Write};
use std::time::Instant;

use chrono::{DateTime, NaiveDateTime, Timelike};
use env_logger::Builder;
use log::LevelFilter;
use tokio::{self, runtime::Runtime, sync};

pub fn unity_log() -> Result<(), Error> {
    const FILTER_DELTA_TIME:i64 = 20000;    // 定义了一个 i32 类型的常量

    //env_logger::init();
    let mut builder = Builder::from_default_env();
    builder.format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args()))
           .filter(None, LevelFilter::Info)
           .init();

    let path = "E:\\Work\\Sausage\\sh\\consoleText_client_package_mirror_release_1753.txt";

    let rt = Runtime::new().unwrap();
    let mut listCost: Vec<(i64, String)> = Vec::new();
    rt.block_on(async {
        let start = Instant::now();
        let input = File::open(path).expect("Error : File::open");
        let lines = BufReader::new(input).lines();
        let mut lines_log: Vec<String> = Vec::new();
        for line in lines {
            let Ok(cur_line) = line else {
                continue;
            };

            lines_log.push(cur_line);
        }

        println!("Tip : read file cost time = {:?}", start.elapsed());

        if lines_log.is_empty() {
            return;
        }

        let start = Instant::now();
        let mut pre_line = String::from(&lines_log[0]);
        let mut count = 0;
        let (tx, mut rx) = sync::mpsc::channel::<(usize, i64, String)>(lines_log.len());
        for line in lines_log {
            if count == 0 {
                count += 1;
                continue;
            }

            let index = count;
            let pre_clone = String::from(&pre_line);
            let cur_clone = String::from(&line);
            let tx_clone: sync::mpsc::Sender<(usize, i64, String)> = tx.clone();
            tokio::spawn(async move {
                let pre_clone_r = pre_clone.find(']');
                if &pre_clone[..1] != "[" || pre_clone_r.is_none() {
                    return;
                }

                trace!("cur_clone({}) = {}", index, cur_clone);
                let cur_clone_r = cur_clone.find(']');
                if &cur_clone[..1] != "[" || cur_clone.find(']').is_none() {
                    return;
                }

                trace!("caps_pre({}) = {}", index, &pre_clone[1..pre_clone_r.unwrap()]);
                let Ok(caps_pre) = DateTime::parse_from_rfc3339(&pre_clone[1..pre_clone_r.unwrap()]) else {
                    return;
                };

                trace!("caps_pre({}) = {}", index, caps_pre.timestamp());

                trace!("caps_cur({}) = {}", index, &cur_clone[1..cur_clone_r.unwrap()]);
                let Ok(caps_cur) = DateTime::parse_from_rfc3339(&cur_clone[1..cur_clone_r.unwrap()]) else {
                    return;
                };

                trace!("caps_cur({}) = {}", index, caps_cur.timestamp());
                debug!("deltaTime({}) = {}", index, caps_cur.timestamp_millis() - caps_pre.timestamp_millis());

                if tx_clone.send((index, caps_cur.timestamp_millis() - caps_pre.timestamp_millis(), pre_clone)).await.is_err() {
                    eprintln!("    Error[copy] : create_dir_all send error");
                }
            });
            pre_line = String::from(&line);
            count += 1;
        }

        drop(tx);

        while let Some((index, delta_time, line)) = rx.recv().await {
            let ts = NaiveDateTime::from_timestamp_millis(delta_time).unwrap();
            if delta_time > FILTER_DELTA_TIME {
                let log_info = format!("Tip : [{}] 耗时 {} ({}:{}:{}) - {}", index, delta_time, ts.hour(), ts.minute(), ts.second(), line);
                listCost.push((delta_time, log_info));
            }
        }

        listCost.sort_by(|a, b| b.0.cmp(&a.0));
        for cost in listCost {
            info!("{}", cost.1);
        }

        println!("Tip : cal cost time = {:?}", start.elapsed());
    });

    Ok(())
}
